/****************************************Copyright (c)****************************************************
**
**
**
**
**---------------------------------------File Info--------------------------------------------------------
** File name:           sysPara.c
** Last modified Date:  2020-6-1
** Last Version:        V0.0
** Descriptions:        系统参数
**
**--------------------------------------------------------------------------------------------------------
** Created by:          刘毅
** Created date:        2020-6-1
** Version:             V0.0
** Descriptions:
**
*********************************************************************************************************/
#include "sysPara.h"

sysPara_t g_sysPara = {0};                                  //系统参数定义
sysPara_t g_sysParaBackup = {0};                            //系统参数备份（用于用户修改的恢复。一键ghost）
sysPara_t g_sysParaShadow = {0};                            //系统参数影子（用于程序自行修改的恢复）

iotPara_t g_iotPara = {0};                                  //物联网配置参数



// 宏定义用于简化初始化
#define PARA_INIT(paraId, curStatus, warnType, thresVal, thresMin, thresMax, thresDelay, resumVal, resumMin, resumMax, resumDelay, greaterThan) \
    {paraId, curStatus, warnType, {{.valueDetail = {.value = thresVal, .minValue = thresMin, .maxValue = thresMax}, .delayMS = thresDelay}, \
                                 {.valueDetail = {.value = resumVal, .minValue = resumMin, .maxValue = resumMax}, .delayMS = resumDelay}}, greaterThan}

const para_t g_defaultParaList[NUM_PARAMETERS] = {
    //==充电告警==
    PARA_INIT(CHARGE_PACK_VOLTAGE, CUR_CHG, ALARM,
              MIN_CELL * 2.0f, MIN_CELL * 1.8f, MIN_CELL * 2.2f, 2000,
              MIN_CELL * 2.0f, MIN_CELL * 1.9f, MIN_CELL * 2.1f, 50, true),
    PARA_INIT(CHARGE_CELL_VOLTAGE, CUR_CHG, ALARM,
              2.0f, 1.9f, 2.1f, 2000,
              2.0f, 1.95f, 2.05f, 50, true),
    PARA_INIT(CHARGE_CURRENT_1, CUR_CHG, ALARM,
              0, -1, 1, 50,
              0, -0.5, 0.5, 50, true),
    PARA_INIT(CHARGE_CURRENT_2, CUR_CHG, ALARM,
              0, -1, 1, 50,
              0, -0.5, 0.5, 50, true),
    PARA_INIT(CHARGE_CELL_HIGH_TEMPERTURE, CUR_CHG, ALARM,
              -40, -45, -35, 50,
              -40, -42, -38, 50, true),
    PARA_INIT(CHARGE_CELL_LOW_TEMPERTURE, CUR_CHG, ALARM,
              -40, -45, -35, 50,
              -40, -42, -38, 50, false),
    PARA_INIT(CHARGE_ENV_HIGH_TEMPERTURE, CUR_CHG, ALARM,
              -40, -45, -35, 50,
              -40, -42, -38, 50, true),
    PARA_INIT(CHARGE_ENV_LOW_TEMPERTURE, CUR_CHG, ALARM,
              -40, -45, -35, 50,
              -40, -42, -38, 50, false),
    PARA_INIT(CHARGE_MOS_HIGH_TEMPERTURE, CUR_CHG, ALARM,
              -40, -45, -35, 50,
              -40, -42, -38, 50, true),

    //==放电告警==
    PARA_INIT(DISCHARGE_PACK_VOLTAGE, CUR_DCHG, ALARM,
              MIN_CELL * 2.0f, MIN_CELL * 1.8f, MIN_CELL * 2.2f, 2000,
              MIN_CELL * 2.0f, MIN_CELL * 1.9f, MIN_CELL * 2.1f, 50, false),
    PARA_INIT(DISCHARGE_CELL_VOLTAGE, CUR_DCHG, ALARM,
              2.0f, 1.9f, 2.1f, 2000,
              2.0f, 1.95f, 2.05f, 50, false),
    PARA_INIT(DISCHARGE_CURRENT_1, CUR_DCHG, ALARM,
              0, -1, 1, 50,
              0, -0.5, 0.5, 50, true),
    PARA_INIT(DISCHARGE_CURRENT_2, CUR_DCHG, ALARM,
              0, -1, 1, 50,
              0, -0.5, 0.5, 50, true),
    PARA_INIT(DISCHARGE_CELL_HIGH_TEMPERTURE, CUR_DCHG, ALARM,
              -40, -45, -35, 50,
              -40, -42, -38, 50, true),
    PARA_INIT(DISCHARGE_CELL_LOW_TEMPERTURE, CUR_DCHG, ALARM,
              -40, -45, -35, 50,
              -40, -42, -38, 50, false),
    PARA_INIT(DISCHARGE_ENV_HIGH_TEMPERTURE, CUR_DCHG, ALARM,
              -40, -45, -35, 50,
              -40, -42, -38, 50, true),
    PARA_INIT(DISCHARGE_ENV_LOW_TEMPERTURE, CUR_DCHG, ALARM,
              -40, -45, -35, 50,
              -40, -42, -38, 50, false),
    PARA_INIT(DISCHARGE_MOS_HIGH_TEMPERTURE, CUR_DCHG, ALARM,
              -40, -45, -35, 50,
              -40, -42, -38, 50, true),

    //==压差告警==
    /*PARA_INIT(CELL_VOLTAGE_DIFFER, CUR_IDLE, ALARM,
              0.1f, 0.08f, 0.12f, 50,
              0.05f, 0.03f, 0.07f, 50, true),
    PARA_INIT(CELL_TEMPERATURE_DIFFER, CUR_IDLE, ALARM,
              1.0f, 0.8f, 1.2f, 50,
              0.5f, 0.3f, 0.7f, 50, true),
    PARA_INIT(HIGH_SOC, CUR_IDLE, ALARM,
              80.0f, 75.0f, 85.0f, 50,
              85.0f, 80.0f, 90.0f, 50, false),

    PARA_INIT(DISCHARGE_CELL_VOLTAGE_DIFFER, CUR_DCHG, ALARM,
              0.1f, 0.08f, 0.12f, 50,
              0.05f, 0.03f, 0.07f, 50, true),
    PARA_INIT(DISCHARGE_CELL_TEMPERATURE_DIFFER, CUR_DCHG, ALARM,
              1.0f, 0.8f, 1.2f, 50,
              0.5f, 0.3f, 0.7f, 50, false),
    PARA_INIT(LOW_SOC, CUR_DCHG, ALARM,
              20.0f, 15.0f, 25.0f, 50,
              25.0f, 20.0f, 30.0f, 50, false),*/

    //==充电保护==
    PARA_INIT(CHARGE_PACK_VOLTAGE, CUR_CHG, PROTECTION,
              MIN_CELL * 2.0f, MIN_CELL * 1.8f, MIN_CELL * 2.2f, 2000,
              MIN_CELL * 2.0f, MIN_CELL * 1.9f, MIN_CELL * 2.1f, 50, true),
    PARA_INIT(CHARGE_CELL_VOLTAGE, CUR_CHG, PROTECTION,
              2.0f, 1.9f, 2.1f, 2000,
              2.0f, 1.95f, 2.05f, 50, true),
    PARA_INIT(CHARGE_CURRENT_1, CUR_CHG, PROTECTION,
              0, -1, 1, 50,
              0, -0.5, 0.5, 50, true),
    PARA_INIT(CHARGE_CURRENT_2, CUR_CHG, PROTECTION,
              0, -1, 1, 50,
              0, -0.5, 0.5, 50, true),
    PARA_INIT(CHARGE_CELL_HIGH_TEMPERTURE, CUR_CHG, PROTECTION,
              -40, -45, -35, 50,
              -40, -42, -38, 50, true),
    PARA_INIT(CHARGE_CELL_LOW_TEMPERTURE, CUR_CHG, PROTECTION,
              -40, -45, -35, 50,
              -40, -42, -38, 50, false),
    PARA_INIT(CHARGE_ENV_HIGH_TEMPERTURE, CUR_CHG, PROTECTION,
              -40, -45, -35, 50,
              -40, -42, -38, 50, true),
    PARA_INIT(CHARGE_ENV_LOW_TEMPERTURE, CUR_CHG, PROTECTION,
              -40, -45, -35, 50,
              -40, -42, -38, 50, false),
    PARA_INIT(CHARGE_MOS_HIGH_TEMPERTURE, CUR_CHG, PROTECTION,
              -40, -45, -35, 50,
              -40, -42, -38, 50, true),

    //==放电保护==
    PARA_INIT(DISCHARGE_PACK_VOLTAGE, CUR_DCHG, PROTECTION,
              MIN_CELL * 2.0f, MIN_CELL * 1.8f, MIN_CELL * 2.2f, 2000,
              MIN_CELL * 2.0f, MIN_CELL * 1.9f, MIN_CELL * 2.1f, 50, false),
    PARA_INIT(DISCHARGE_CELL_VOLTAGE, CUR_DCHG, PROTECTION,
              2.0f, 1.9f, 2.1f, 2000,
              2.0f, 1.95f, 2.05f, 50, false),
    PARA_INIT(DISCHARGE_CURRENT_1, CUR_DCHG, PROTECTION,
              0, -1, 1, 50,
              0, -0.5, 0.5, 50, true),
    PARA_INIT(DISCHARGE_CURRENT_2, CUR_DCHG, PROTECTION,
              0, -1, 1, 50,
              0, -0.5, 0.5, 50, true),
    PARA_INIT(DISCHARGE_CELL_HIGH_TEMPERTURE, CUR_DCHG, PROTECTION,
              -40, -45, -35, 50,
              -40, -42, -38, 50, true),
    PARA_INIT(DISCHARGE_CELL_LOW_TEMPERTURE, CUR_DCHG, PROTECTION,
              -40, -45, -35, 50,
              -40, -42, -38, 50, false),
    PARA_INIT(DISCHARGE_ENV_HIGH_TEMPERTURE, CUR_DCHG, PROTECTION,
              -40, -45, -35, 50,
              -40, -42, -38, 50, true),
    PARA_INIT(DISCHARGE_ENV_LOW_TEMPERTURE, CUR_DCHG, PROTECTION,
              -40, -45, -35, 50,
              -40, -42, -38, 50, false),
    PARA_INIT(DISCHARGE_MOS_HIGH_TEMPERTURE, CUR_DCHG, PROTECTION,
              -40, -45, -35, 50,
              -40, -42, -38, 50, true),

    /*//==压差保护==
    PARA_INIT(CELL_VOLTAGE_DIFFER, CUR_CHG, PROTECTION,
              0.1f, 0.08f, 0.12f, 50,
              0.05f, 0.03f, 0.07f, 50, true),
    PARA_INIT(CELL_TEMPERATURE_DIFFER, CUR_CHG, PROTECTION,
              1.0f, 0.8f, 1.2f, 50,
              0.5f, 0.3f, 0.7f, 50, true),
    PARA_INIT(HIGH_SOC, CUR_CHG, PROTECTION,
              80.0f, 75.0f, 85.0f, 50,
              85.0f, 80.0f, 90.0f, 50, true),
    PARA_INIT(DISCHARGE_CELL_VOLTAGE_DIFFER, CUR_DCHG, PROTECTION,
              0.1f, 0.08f, 0.12f, 50,
              0.05f, 0.03f, 0.07f, 50, true),
    PARA_INIT(DISCHARGE_CELL_TEMPERATURE_DIFFER, CUR_DCHG, PROTECTION,
              1.0f, 0.8f, 1.2f, 50,
              0.5f, 0.3f, 0.7f, 50, false),
    PARA_INIT(LOW_SOC, CUR_DCHG, PROTECTION,
              20.0f, 15.0f, 25.0f, 50,
              25.0f, 20.0f, 30.0f, 50, false)*/
};

/*========================================================================================================
**函数名称：SYS_SavePara
**函数功能：保存系统参数
**入口参数：obj--->要保存的参数对象【工作参数、备份参数、影子参数】
**出口参数：无
**编    写：刘毅     时间：2020-6-1
**修    改：           时间：2021-6-2
**说    明：
========================================================================================================*/
void SYS_SavePara(sysParaObj_t obj)
{
    switch((rt_uint8_t)obj)
    {
        case SYS_OBJ_SHADOW:
            //FLASH_Write(FLASH_PARA_SHADOW_START, g_sysParaShadow.buf, sizeof(g_sysParaShadow));
        break;
        case SYS_OBJ_BACKUP:
            //FLASH_Write(FLASH_PARA_BACKUP_START, g_sysParaBackup.buf, sizeof(g_sysParaBackup));
        break;
        case SYS_OBJ_WORKING:
            //FLASH_Write(FLASH_PARA_WORKING_START, g_sysPara.buf, sizeof(g_sysPara));
        break;
        case SYS_OBJ_IOT:
            //FLASH_Write(FLASH_PARA_IOT_START, g_iotPara.buf, sizeof(g_iotPara));
        break;
        default:
        break;
    }
}

/*========================================================================================================
**函数名称：SYS_LoadPara
**函数功能：装载系统参数
**入口参数：forceFactory--->强制恢复出厂参数
**出口参数：无
**编    写：刘毅     时间：2020-6-1
**修    改：           时间：
**说    明：
========================================================================================================*/
void SYS_LoadPara(bool forceFactory)
{
    rt_uint16_t i = 0;

    //FLASH_Read(FLASH_PARA_WORKING_START, g_sysPara.buf, sizeof(g_sysPara));
    for(i=0; i<sizeof(g_sysPara); i++)
    {
        if(g_sysPara.buf[i] != 0xFF) {break;}
    }
    if(forceFactory || (i >= sizeof(g_sysPara)))                                            //强制恢复出厂设置或者flash未写过
    {
//=======填充默认参数------------------------------------------------------------------------------------
        memset(g_sysPara.buf, 0, sizeof(g_sysPara));
        memcpy(g_sysPara.runPara.paraList,g_defaultParaList,sizeof(g_defaultParaList));

//=======制造参数-----------------------------------------------------------------------------------------
        g_sysPara.producePara.cellNum = 16;                                                 //电芯数量
        g_sysPara.producePara.cellNtcNum = 4;                                               //电芯温度传感器数量
        g_sysPara.producePara.inclinationBase = 0;                                          //PCB在电池里竖直安装
        g_sysPara.producePara.ratedCapacityAh = 100;                                        //额定容量100Ah
        memcpy(g_sysPara.producePara.pcbSn, "PCB_17774966161", strlen("PCB_17774966161"));
        memcpy(g_sysPara.producePara.batterySn, "BAT_15123276561", strlen("BAT_15123276561"));
        memcpy(g_sysPara.producePara.model, "SCIFP48100", strlen("SCIFP48100"));


//=======校准参数-----------------------------------------------------------------------------------------
        g_sysPara.runPara.calib.times_10.mlGIM = 10.0f;                                     //理论值为10倍增益
        g_sysPara.runPara.calib.times_10.mlVIMZ = 1.0f;                                     //理论基准为1V
        g_sysPara.runPara.calib.times_50.mlGIM = 50.0f;                                     //理论值为50倍增益
        g_sysPara.runPara.calib.times_50.mlVIMZ = 1.0f;                                     //理论基准为1V
        g_sysPara.runPara.calib.shunt = 0.002f / 8;                                         //焊接分流器标称（2mR/8个）
        g_sysPara.runPara.calib.chgI_50 = 0.02f / g_sysPara.runPara.calib.shunt;            //50倍增益时充电满程电流(1.0V/50=0.020V)
        g_sysPara.runPara.calib.dchgI_50 = 0.046f / g_sysPara.runPara.calib.shunt;          //50倍增益时放电满程电流(2.3V/50=0.046v)
        g_sysPara.runPara.calib.usegGim50 = false;                                          //默认不使用50倍增益
        g_sysPara.runPara.calib.calibing = false;                                           //正在校准时不会自动切换增益

//=======防盗参数-----------------------------------------------------------------------------------------
        g_sysPara.runPara.antitheft.mode = ATF_NONE;                                        //默认不启动防盗
        g_sysPara.runPara.antitheft.physicDelayMS = 1000;                                   //物理防盗超时上锁时间1秒
        g_sysPara.runPara.antitheft.linkDelayMS = 10 * 60 * 60 *1000;                       //通信超时上锁时间10小时

//=======限流参数-----------------------------------------------------------------------------------------
        g_sysPara.runPara.currentLimit.mode = CL_TRIG;                                      //触发(被动)限流模式
        g_sysPara.runPara.currentLimit.limitValue = 10;                                     //10A限流
        g_sysPara.runPara.currentLimit.trigValue = 50;                                      //超过50A则触发限流
        g_sysPara.runPara.currentLimit.trigDelayMS = 500;                                   //触发防抖时间为500ms
        g_sysPara.runPara.currentLimit.retryDelayMS = 5 * 60 * 1000;                        //重试时间为5分钟

//=======间歇充电参数-------------------------------------------------------------------------------------
        g_sysPara.runPara.intermitChg.en = false;                                           //不开启间歇充电
        g_sysPara.runPara.intermitChg.trigSoc = 95;                                         //超过95%则触发间歇充电
        g_sysPara.runPara.intermitChg.trigDelayMS = 1000;                                   //触发防抖时间为1秒
        g_sysPara.runPara.intermitChg.intermitMS = 30 * 60 * 1000;                          //间歇时间为30分钟

//=======日志参数-----------------------------------------------------------------------------------------
        //g_sysPara.runPara.logPara.writeAddr = SF_BASE_ADDR;                                 //日志写到外部串行FLASH中
        //g_sysPara.runPara.logPara.readAddr = SF_BASE_ADDR;                                  //日志从外部串行FLASH中读取
        g_sysPara.runPara.logPara.autoLogInterval = 3600;                                   //默认间隔1小时自动记录一次
        g_sysPara.runPara.logPara.emptyFlag = true;                                         //初始记录为空
        g_sysPara.runPara.logPara.fullFlag = false;                                         //初始没有满
        g_sysPara.runPara.logPara.logCapacity = 10000;                                      //默认记录10000条记录
        g_sysPara.runPara.logPara.logSize = sizeof(log_t);                                  //每条记录大小根据log内容变化
        g_sysPara.runPara.logPara.record.en = false;                                        //密集录波功能不开启
        g_sysPara.runPara.logPara.record.interval = 60;                                     //密集录波时间间隔默认60秒
        g_sysPara.runPara.logPara.record.startTime = 0;                                     //密集录波开始时间
        g_sysPara.runPara.logPara.record.timeSpan = 0;                                      //密集录波时长

//=======均衡参数----------------------------------------------------------------------------------------
        g_sysPara.runPara.balancePara.en = 0;                                               //均衡默认不使能
        g_sysPara.runPara.balancePara.minSoc= 90.0f;                                        //均衡开启最小SOC为90%
        g_sysPara.runPara.balancePara.volatageDiff = 0.03f;                                 //均衡开启电压为30mV
        g_sysPara.runPara.balancePara.voltageAverage = 3.2f;                                //均衡开启平均电芯电压为3.2V

//=======功能开关参数------------------------------------------------------------------------------------
        g_sysPara.runPara.functionEn.beepEn = true;                                         //蜂鸣器可以鸣响
        g_sysPara.runPara.functionEn.heatEn = false;                                        //加热功能不启用
        g_sysPara.runPara.functionEn.maintainEn = false;                                    //维护模式
        g_sysPara.runPara.functionEn.sleepEn = true;                                        //待机休眠开关

//=======数值参数----------------------------------------------------------------------------------------
        g_sysPara.runPara.numeric.underVoltage2sleepTimeS = 30 * 60;                        //欠压休眠时间为30分钟【30分钟后进入休眠】
        g_sysPara.runPara.numeric.fullCapacityAh = g_sysPara.producePara.ratedCapacityAh;   //满充容量初始为额定容量
        g_sysPara.runPara.numeric.remainCapacityAh = 50;                                    //初始剩余容量50%
        g_sysPara.runPara.numeric.totalChgTimeH = 0;                                        //总充时间
        g_sysPara.runPara.numeric.totalChgCapacityAh = 0;                                   //总充容量
        g_sysPara.runPara.numeric.totalChgEnergyKwh = 0;                                    //总充能量
        g_sysPara.runPara.numeric.totalDchgTimeH = 0;                                       //总放时间
        g_sysPara.runPara.numeric.totalDchgCapacityAh = 0;                                  //总放容量
        g_sysPara.runPara.numeric.totalDchgEnergyKwh = 0;                                   //总放能量
        g_sysPara.runPara.numeric.cycleCount = 0;                                           //循环次数

//=======定制参数-----------------------------------------------------------------------------------------
        g_sysPara.customPara.modbusFirm = MB_SACRED;                                        //MODBUS协议厂商
        g_sysPara.customPara.modBus_OV_Mask = true;                                         //modbus屏蔽过压信息上报
        g_sysPara.customPara.batteryMixEn = false;                                          //铅锂混合
        g_sysPara.customPara.mixLiQuitTimeMin = 60;                                         //铅锂混用时锂电退出时间10分钟

        SYS_SavePara(SYS_OBJ_WORKING);
    }
    g_sysParaShadow = g_sysPara;
    SYS_SavePara(SYS_OBJ_SHADOW);
}


static void timer_callback(void *parameter)
{
    paraContext_t *ctx = (paraContext_t *)parameter;

    switch (ctx->state)
    {
        case STATE_WAIT_THRESHOLD_CONFIRM:
            if ((ctx->greater_than && ctx->current_value > ctx->param.paraValue.threshold.delayMS) ||
                (!ctx->greater_than && ctx->current_value < ctx->param.paraValue.threshold.valueDetail.value))
            {
                if (ctx->threshold_cb)
                {
                    ctx->threshold_cb();
                }
                ctx->state = STATE_WAIT_RESUME_CONFIRM;
                rt_timer_control(ctx->timer, RT_TIMER_CTRL_SET_TIME, &ctx->param.paraValue.resume.delayMS);
                rt_timer_start(ctx->timer);
            }
            break;

        case STATE_WAIT_RESUME_CONFIRM:
            if ((ctx->greater_than && ctx->current_value < ctx->param.paraValue.resume.valueDetail.value) ||
                (!ctx->greater_than && ctx->current_value > ctx->param.paraValue.resume.valueDetail.value))
            {
                if (ctx->resume_cb)
                {
                    ctx->resume_cb();
                }
                ctx->state = STATE_INIT;
            }
            break;

        default:
            break;
    }
}

void para_init(paraContext_t *ctx, const para_t *param, event_callback_t threshold_cb, event_callback_t resume_cb)
{
    ctx->param = *param;
    ctx->threshold_cb = threshold_cb;
    ctx->resume_cb = resume_cb;
    ctx->current_value = 0.0f;
    ctx->state = STATE_INIT;
    ctx->greater_than = param->greater_than;  // 设置比较方向

    // Create a timer
    ctx->timer = rt_timer_create("paraTimer", timer_callback, ctx, ctx->param.paraValue.threshold.delayMS, RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER);
    if (ctx->timer == RT_NULL)
    {
        rt_kprintf("Failed to create timer\n");
    }
}

void para_update_value(paraContext_t *ctx, float new_value)
{
    ctx->current_value = new_value;

    switch (ctx->state)
    {
        case STATE_INIT:
            if ((ctx->greater_than && new_value > ctx->param.paraValue.threshold.valueDetail.value) ||
                (!ctx->greater_than && new_value < ctx->param.paraValue.threshold.valueDetail.value))
            {
                ctx->state = STATE_WAIT_THRESHOLD_CONFIRM;
                rt_timer_control(ctx->timer, RT_TIMER_CTRL_SET_TIME, &ctx->param.paraValue.threshold.delayMS);
                rt_timer_start(ctx->timer);
            }
            break;

        case STATE_WAIT_THRESHOLD_CONFIRM:
            // Wait for the timer to confirm
            break;

        case STATE_WAIT_RESUME_CONFIRM:
            // Wait for the timer to confirm
            break;

        default:
            break;
    }
}

/*********************************************************************************************************
**  End Of File
**  在烧写的时候是FLASH中的被占用的空间为:      Code + RO-data + RW-data
**  程序运行的时候，芯片内部RAM使用的空间为:    RW-data + ZI-data
*********************************************************************************************************/
